home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / prefix / export.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  14.3 KB  |  511 lines

  1. /***********************************************************************
  2.  *
  3.  * PROJECT:      PMake
  4.  * MODULE:      Prefix -- Exportation
  5.  * FILE:      export.c
  6.  *
  7.  * AUTHOR:        Adam de Boor: Jul  5, 1989
  8.  *
  9.  * ROUTINES:
  10.  *    Name              Description
  11.  *    ----              -----------
  12.  *    Export_Prefix        Export a directory as a prefix
  13.  *    Export_Send         Send list of exported prefixes to the local
  14.  *                        daemon.
  15.  *    Export_Init         Initialize the module.
  16.  *    Export_Dump         Dump list of exported prefixes into a buffer.
  17.  *
  18.  * REVISION HISTORY:
  19.  *    Date      Name        Description
  20.  *    ----      ----        -----------
  21.  *    7/ 5/89      ardeb        Initial version
  22.  *
  23.  * DESCRIPTION:
  24.  *    Functions to handle exporting of various prefixes. Doesn't take
  25.  *    the place of the standard mount daemon. Just responds to queries
  26.  *    about where a prefix is defined.
  27.  *
  28.  *     Copyright (c) Berkeley Softworks 1989
  29.  *     Copyright (c) Adam de Boor 1989
  30.  *
  31.  *     Permission to use, copy, modify, and distribute this
  32.  *     software and its documentation for any non-commercial purpose
  33.  *    and without fee is hereby granted, provided that the above copyright
  34.  *     notice appears in all copies.  Neither Berkeley Softworks nor
  35.  *     Adam de Boor makes any representations about the suitability of this
  36.  *     software for any purpose.  It is provided "as is" without
  37.  *     express or implied warranty.
  38.  *
  39.  ***********************************************************************/
  40. #ifndef lint
  41. static char *rcsid =
  42. "$Id: export.c,v 1.9 89/11/14 17:16:05 adam Exp $";
  43. #endif lint
  44.  
  45. #include    "prefix.h"
  46. #include    "rpc.h"
  47.  
  48. #include    <ctype.h>
  49. #include    <netdb.h>
  50. #include    <arpa/inet.h>
  51.  
  52. typedef struct {
  53.     char        *fsname;        /* Name of file system being exported */
  54.     char        *prefix;        /* Prefix under which it's being exported */
  55.     int            active;            /* Actively exported. An inactively
  56.                  * exported prefix is one that the user
  57.                  * wants to delete, but can't because
  58.                  * some client is using the FS. Setting this
  59.                  * false keeps ExportLocate from responding */
  60. } Export;
  61.  
  62. static Lst  exports;
  63.  
  64.  
  65. /***********************************************************************
  66.  *                ExportLocate
  67.  ***********************************************************************
  68.  * SYNOPSIS:        Handle a PREFIX_LOCATE broadcast call
  69.  * CALLED BY:        Rpc module
  70.  * RETURN:        Local directory, if we're exporting the prefix
  71.  * SIDE EFFECTS:    None
  72.  *
  73.  * STRATEGY:
  74.  *
  75.  * REVISION HISTORY:
  76.  *    Name    Date        Description
  77.  *    ----    ----        -----------
  78.  *    ardeb    7/ 6/89        Initial Revision
  79.  *
  80.  ***********************************************************************/
  81. static void
  82. ExportLocate(from, msg, dataLen, data, serverData)
  83.     struct sockaddr_in        *from;      /* Source of call */
  84.     Rpc_Opaque                msg;        /* Message token for reply */
  85.     int                        dataLen;    /* Length of passed data */
  86.     Rpc_Opaque                data;       /* Name of prefix being sought */
  87.     Rpc_Opaque                serverData;    /* JUNK */
  88. {
  89.     dprintf("LOCATE from %s for %s\n", InetNtoA(from->sin_addr),
  90.         data);
  91.         
  92.     if (exports) {
  93.     LstNode         ln;
  94.     Export          *ep;
  95.     
  96.     for (ln = Lst_First(exports); ln != NILLNODE; ln = Lst_Succ(ln)) {
  97.         ep = (Export *)Lst_Datum(ln);
  98.  
  99.         if ((strcmp(ep->prefix, (char *)data) == 0) && ep->active) {
  100.         /*
  101.          * We've got it -- answer the call (follow the fold
  102.          * and stray no more! Stray no more! ...)
  103.          */
  104.         Rpc_Return(msg, strlen(ep->fsname)+1, ep->fsname);
  105.         break;
  106.         }
  107.     }
  108.     }
  109. }
  110.  
  111.  
  112. /***********************************************************************
  113.  *                Export_Prefix
  114.  ***********************************************************************
  115.  * SYNOPSIS:        Arrange to export a directory under a prefix
  116.  * CALLED BY:        main
  117.  * RETURN:        Nothing
  118.  * SIDE EFFECTS:    An Export structure is added to the exports list
  119.  *
  120.  * STRATEGY:
  121.  *
  122.  * REVISION HISTORY:
  123.  *    Name    Date        Description
  124.  *    ----    ----        -----------
  125.  *    ardeb    7/ 6/89        Initial Revision
  126.  *
  127.  ***********************************************************************/
  128. void
  129. Export_Prefix(fsname, prefix)
  130.     char        *fsname;        /* Filesystem being exported */
  131.     char        *prefix;        /* Name under which it's being exported */
  132. {
  133.     Export      *ep;
  134.     FILE        *ef;
  135.     LstNode     ln;
  136.     
  137.     if (exports == NULL) {
  138.     exports = Lst_Init(FALSE);
  139.     }
  140.  
  141.     dprintf("export %s as %s\n", fsname, prefix);
  142.  
  143.     /*
  144.      * See if we're replacing an existing prefix...
  145.      */
  146.     for (ln = Lst_First(exports); ln != NILLNODE; ln = Lst_Succ(ln)) {
  147.     ep = (Export *)Lst_Datum(ln);
  148.  
  149.     if (strcmp(prefix, ep->prefix) == 0) {
  150.         break;
  151.     }
  152.     }
  153.     if (ln == NILLNODE) {
  154.     /*
  155.      * Nope -- allocate a new Export record and stick it on the end
  156.      * of the list.
  157.      */
  158.     ep = (Export *)malloc(sizeof(Export));
  159.     (void)Lst_AtEnd(exports, (ClientData)ep);
  160.     }
  161.  
  162.     /*
  163.      * Save the parameters in the record
  164.      */
  165.     ep->fsname = fsname;
  166.     ep->prefix = prefix;
  167.     ep->active = TRUE;
  168.  
  169.     /*
  170.      * Make sure the filesystem is exported, warning if it isn't.
  171.      */
  172.     ef = fopen(EXPORTS, "r");
  173.     if (ef == NULL) {
  174.     Message("/etc/exports doesn't exist -- %s won't be allowed out",
  175.         fsname);
  176.     } else {
  177.     char       line[512];
  178.     int     fslen = strlen(fsname);
  179.  
  180.     while (fgets(line, sizeof(line), ef) != NULL) {
  181.         if ((strncmp(line, fsname, fslen) == 0) &&
  182.         isspace(line[fslen]))
  183.         {
  184.         fclose(ef);
  185.         return;
  186.         }
  187.     }
  188.     fclose(ef);
  189.     Message("%s not in /etc/exports -- won't be allowed out", fsname);
  190.     }
  191. }
  192.     
  193.  
  194. /***********************************************************************
  195.  *                ExportExport
  196.  ***********************************************************************
  197.  * SYNOPSIS:        Export another directory as a prefix
  198.  * CALLED BY:        PREFIX_EXPORT
  199.  * RETURN:        Nothing
  200.  * SIDE EFFECTS:    An Export record is added to the exports list
  201.  *
  202.  * STRATEGY:
  203.  *
  204.  * REVISION HISTORY:
  205.  *    Name    Date        Description
  206.  *    ----    ----        -----------
  207.  *    ardeb    7/ 7/89        Initial Revision
  208.  *
  209.  ***********************************************************************/
  210. static void
  211. ExportExport(from, msg, len, data, serverData)
  212.     struct sockaddr_int    *from;
  213.     Rpc_Message            msg;
  214.     int                    len;
  215.     Rpc_Opaque            data;    /* Buffer holding both dir (first string)
  216.                  * and prefix, separated by a null character */
  217.     Rpc_Opaque            serverData;    /* Data we gave (UNUSED) */
  218. {
  219.     char        *cp;
  220.     char    *args = (char *)data;
  221.     char    *fsname;
  222.     char    *prefix;
  223.  
  224.     cp = args + strlen(args) + 1;
  225.  
  226.     fsname = (char *)malloc(strlen(args) + 1);
  227.     strcpy(fsname, args);
  228.  
  229.     prefix = (char *)malloc(strlen(cp) + 1);
  230.     strcpy(prefix, cp);
  231.  
  232.     Export_Prefix(fsname, prefix);
  233.  
  234.     Rpc_Return(msg, 0, NULL);
  235. }
  236.  
  237.  
  238. /***********************************************************************
  239.  *                Export_Send
  240.  ***********************************************************************
  241.  * SYNOPSIS:        Send all exported prefixes to the local daemon
  242.  * CALLED BY:        main
  243.  * RETURN:        Nothing
  244.  * SIDE EFFECTS:    None
  245.  *
  246.  * STRATEGY:
  247.  *
  248.  * REVISION HISTORY:
  249.  *    Name    Date        Description
  250.  *    ----    ----        -----------
  251.  *    ardeb    7/ 7/89        Initial Revision
  252.  *
  253.  ***********************************************************************/
  254. void
  255. Export_Send(server)
  256.     struct sockaddr_in        *server;
  257. {
  258.     LstNode        ln;            /* Node in exports list */
  259.     Export          *ep;        /* Current exported prefix */
  260.     char            buf[512];    /* Transmission buffer */
  261.     int                len;        /* Length of parameters */
  262.     struct timeval  retry;      /* Retransmission interval */
  263.     Rpc_Stat        status;     /* Status of call */
  264.  
  265.     retry.tv_sec = 1;
  266.     retry.tv_usec = 0;
  267.     
  268.     if (exports) {
  269.     for (ln = Lst_First(exports); ln != NILLNODE; ln = Lst_Succ(ln)) {
  270.         ep = (Export *)Lst_Datum(ln);
  271.  
  272.         len = strlen(ep->fsname);
  273.         strcpy(buf, ep->fsname);
  274.         
  275.         strcpy(buf+len+1,ep->prefix);
  276.  
  277.         len += strlen(ep->prefix) + 2;
  278.  
  279.         status = Rpc_Call(prefixSock, server, PREFIX_EXPORT,
  280.                  len, buf,
  281.                  0, NULL,
  282.                  2, &retry);
  283.         if (status != RPC_SUCCESS) {
  284.         fprintf(stderr, "Couldn't export %s as %s (%s)\n", ep->fsname,
  285.             ep->prefix, Rpc_ErrorMessage(status));
  286.         }
  287.     }
  288.     }
  289. }
  290.  
  291.  
  292. /***********************************************************************
  293.  *                Export_Dump
  294.  ***********************************************************************
  295.  * SYNOPSIS:        Dump the list of exported prefixes into a buffer.
  296.  * CALLED BY:        DumpPrefix
  297.  * RETURN:        *leftPtr adjusted to reflect space remaining.
  298.  * SIDE EFFECTS:    None
  299.  *
  300.  * STRATEGY:
  301.  *    Each exported prefix is placed in the buffer as:
  302.  *        x<fsname>:<prefix>\n
  303.  *
  304.  * REVISION HISTORY:
  305.  *    Name    Date        Description
  306.  *    ----    ----        -----------
  307.  *    ardeb    7/ 8/89        Initial Revision
  308.  *
  309.  ***********************************************************************/
  310. void
  311. Export_Dump(buf, leftPtr)
  312.     char        *buf;        /* Place to start storing */
  313.     int            *leftPtr;   /* IN/OUT: remaining room in buf */
  314. {
  315.     LstNode     ln;
  316.     Export      *ep;
  317.  
  318.     if (exports) {
  319.     for (ln = Lst_First(exports); ln != NILLNODE; ln = Lst_Succ(ln)) {
  320.         int        entlen;
  321.         
  322.         ep = (Export *)Lst_Datum(ln);
  323.         entlen = 1+strlen(ep->fsname)+1+strlen(ep->prefix)+1+2;
  324.  
  325.         if (*leftPtr >= entlen) {
  326.         sprintf(buf, "x%s:%s:%c\n", ep->fsname, ep->prefix,
  327.             ep->active ? '1' : '0');
  328.         buf += entlen;
  329.         *leftPtr -= entlen;
  330.         }
  331.     }
  332.     }
  333. }
  334.  
  335.  
  336. /***********************************************************************
  337.  *                ExportUnmountResponse
  338.  ***********************************************************************
  339.  * SYNOPSIS:        Handle a response to our PREFIX_UNMOUNT call
  340.  * CALLED BY:        Rpc_Broadcast
  341.  * RETURN:        FALSE (keep broadcasting)
  342.  * SIDE EFFECTS:    *msgPtr advanced.
  343.  *
  344.  * STRATEGY:
  345.  *
  346.  * REVISION HISTORY:
  347.  *    Name    Date        Description
  348.  *    ----    ----        -----------
  349.  *    ardeb    7/11/89        Initial Revision
  350.  *
  351.  ***********************************************************************/
  352. static Boolean
  353. ExportUnmountResponse(from, len, data, msgPtr, serverData)
  354.     struct sockaddr_in    *from;        /* Source of reply */
  355.     int                    len;        /* Length of returned data */
  356.     Rpc_Opaque            data;        /* Returned data (s/b none) */
  357.     char                **msgPtr;   /* Place to store hostname (message
  358.                      * being formed for return to caller) */
  359.     Rpc_Opaque            serverData; /* Data we gave (UNUSED) */
  360. {
  361.     struct hostent      *he;
  362.  
  363.     he = gethostbyaddr(&from->sin_addr, sizeof(from->sin_addr), AF_INET);
  364.  
  365.     sprintf(*msgPtr, "%s, ", he ? he->h_name : InetNtoA(from->sin_addr));
  366.     *msgPtr += strlen(*msgPtr);
  367.  
  368.     return(FALSE);
  369. }
  370.  
  371.  
  372. /***********************************************************************
  373.  *                ExportDelete
  374.  ***********************************************************************
  375.  * SYNOPSIS:        Delete an exported prefix
  376.  * CALLED BY:        PREFIX_NOEXPORT
  377.  * RETURN:        Nothing
  378.  * SIDE EFFECTS:    If the prefix exists in the export record, it is
  379.  *                deleted.
  380.  *
  381.  * STRATEGY:
  382.  *
  383.  * REVISION HISTORY:
  384.  *    Name    Date        Description
  385.  *    ----    ----        -----------
  386.  *    ardeb    7/ 8/89        Initial Revision
  387.  *
  388.  ***********************************************************************/
  389. static void
  390. ExportDelete(from, msg, len, data, serverData)
  391.     struct sockaddr_in    *from;        /* Source of data */
  392.     Rpc_Message        msg;        /* Message for reply/return */
  393.     int            len;        /* Length of prefix (including null) */
  394.     Rpc_Opaque        data;        /* Null-terminated prefix */
  395.     Rpc_Opaque             serverData; /* Data we gave (UNUSED) */
  396. {
  397.     char            ansbuf[1024];    /* Buffer for response (1K
  398.                      * enough?) */
  399.     char                *answer = "Ok";    /* Assume ok */
  400.  
  401.     if (exports) {
  402.     LstNode            ln;     /* Node for current exported prefix */
  403.     Export            *ep;    /* Exported prefix being checked */
  404.  
  405.     for (ln = Lst_First(exports); ln != NILLNODE; ln = Lst_Succ(ln)) {
  406.         ep = (Export *)Lst_Datum(ln);
  407.  
  408.         if (strcmp(ep->prefix, (char *)data) == 0) {
  409.         struct timeval    retry;            /* Retrans interval for
  410.                          * broadcast */
  411.         char            *cp;            /* Pointer to pass to
  412.                          * Rpc_Broadcast */
  413.         struct sockaddr_in server;      /* Nothingness to tell
  414.                          * Rpc_Broadcast to go
  415.                          * everywhere */
  416.         Rpc_Stat        status;            /* Status of broadcast */
  417.         
  418.         /*
  419.          * Tell the world the prefix is going away, after marking the
  420.          * prefix as inactive, preventing us from exporting it
  421.          * during the broadcast.
  422.          */
  423.         ep->active = FALSE;
  424.  
  425.         server.sin_family = AF_INET;
  426.         server.sin_port = htons(PREFIX_PORT);
  427.         server.sin_addr.s_addr = INADDR_ANY;
  428.  
  429.         /*
  430.          * 1-second intervals, so we don't keep the user waiting
  431.          * too long, there being no shortcut out of the broadcast.
  432.          */
  433.         retry.tv_sec = 1;
  434.         retry.tv_usec = 0;
  435.         
  436.         cp = ansbuf;
  437.         
  438.         status = Rpc_Broadcast(prefixSock, &server, PREFIX_UNMOUNT,
  439.                        strlen(ep->prefix)+1,
  440.                        (Rpc_Opaque)ep->prefix,
  441.                        0, (Rpc_Opaque)NULL,
  442.                        2, &retry,
  443.                        ExportUnmountResponse,
  444.                        (Rpc_Opaque)&cp);
  445.  
  446.         if (status != RPC_SUCCESS && status != RPC_TIMEDOUT) {
  447.             answer = Rpc_ErrorMessage(status);
  448.             dprintf("Rpc_Broadcast: %s\n", answer);
  449.         } else if (cp != ansbuf) {
  450.             /*
  451.              * Objection! The name(s) of the objector(s) is in
  452.              * answer, separated by commas. Make a sentence out of
  453.              * the response and ship it back, leaving the prefix
  454.              * marked inactive.
  455.              */
  456.             cp[-2] = ' '; /* Blow away final comma */
  457.             /*
  458.              * Tack on end o' message, nuking extraneous space
  459.              */
  460.             strcpy(&cp[-1], "still using it");
  461.             answer = ansbuf;
  462.         } else {
  463.             /*
  464.              * Remove the prefix from the export list
  465.              */
  466.             (void)Lst_Remove(exports, ln);
  467.             
  468.             /*
  469.              * Free all associated memory
  470.              */
  471.             free(ep->prefix);
  472.             free(ep->fsname);
  473.             free((char *)ep);
  474.         }
  475.         }
  476.     }
  477.     } else {
  478.     answer = "no prefixes exported";
  479.     }
  480.     Rpc_Return(msg, strlen(answer)+1, answer);
  481. }
  482.  
  483. /***********************************************************************
  484.  *                Export_Init
  485.  ***********************************************************************
  486.  * SYNOPSIS:        Initialize this module
  487.  * CALLED BY:        main
  488.  * RETURN:        Nothing
  489.  * SIDE EFFECTS:    Our RPC servers are registered
  490.  *
  491.  * STRATEGY:
  492.  *
  493.  * REVISION HISTORY:
  494.  *    Name    Date        Description
  495.  *    ----    ----        -----------
  496.  *    ardeb    7/ 6/89        Initial Revision
  497.  *
  498.  ***********************************************************************/
  499. void
  500. Export_Init()
  501. {
  502.     Rpc_ServerCreate(prefixSock, PREFIX_LOCATE, ExportLocate, NULL, NULL,
  503.              NULL);
  504.     Rpc_ServerCreate(prefixSock, PREFIX_EXPORT, ExportExport, NULL, NULL,
  505.              NULL);
  506.     Rpc_ServerCreate(prefixSock, PREFIX_NOEXPORT, ExportDelete, NULL, NULL,
  507.              NULL);
  508.     
  509. }
  510.  
  511.